package dao;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;

import entity.OrganizationElement;
import entity.Usuario;

import util.HibernateUtil;
import vo.OrganizationVO;
import vo.UsuarioVO;

public class UsuarioDAO {
	
	public int verificaLogin(String login, String senha){
		int retorno;
		
		UsuarioVO u = getUser(login);
		
		if (u.getId() <= 0)
			retorno = 1;
		else{			
			senha = codificaSenha(senha);
			
			if (u.getSenha().equalsIgnoreCase(senha))
				retorno = 0;
			else
				retorno = 2;
		}
		
		return retorno;
	}
	
	private String codificaSenha(String senha){
		String senhaNova;
		
		try{
			MessageDigest md = MessageDigest.getInstance("MD5");  
		    md.update(senha.getBytes());  
			BigInteger hash = new BigInteger(1, md.digest());  
			senhaNova = hash.toString(16);
		}
		catch(Exception e){
			senhaNova = "";
		}
		
		return senhaNova;
	}

	private Criteria handleFilter(UsuarioVO vo, Session sessao){
		Criteria criterios = sessao.createCriteria(Usuario.class);
		
		Usuario u = new Usuario();
		
		if ((vo.getLogin() != null) && (! vo.getLogin().equalsIgnoreCase(""))){
			u.setLogin(vo.getLogin());
		}
		
		if ((vo.getSenha() != null) && (! vo.getSenha().equalsIgnoreCase(""))){
			u.setSenha(vo.getSenha());
		}
		
		if ((vo.getNome() != null) && (! vo.getNome().equalsIgnoreCase(""))){
			u.setNome(vo.getNome());
		}
		
		criterios.add(Example.create(u).enableLike(MatchMode.ANYWHERE));
		return criterios;
	}

	public List<UsuarioVO> searchUser(UsuarioVO vo){
		Session sessao = HibernateUtil.getSession();
		Criteria criterios = handleFilter(vo, sessao);		
		List<?> resultado = criterios.list();
		
		List<UsuarioVO> listaResultado = new ArrayList<UsuarioVO>();
		for(Object obj:resultado){
			Usuario u = (Usuario) obj;
			UsuarioVO usuario = new UsuarioVO();
			
			usuario.setLogin(u.getLogin());
			usuario.setNome(u.getNome());
			usuario.setId(u.getId());
			usuario.setSenha(u.getSenha());
			
			listaResultado.add(usuario);
		}
		
		sessao.close();
		return listaResultado;
	}

	public int insertUser(UsuarioVO vo) {
		int retorno;
		
		Session sessao = HibernateUtil.getSession();
		
		if (existeLogin(vo.getLogin())){
			retorno = 1;
		}
		else{
			Transaction tx = sessao.beginTransaction();
			try{				
				Usuario u = new Usuario();
				u.setNome(vo.getNome());
				u.setLogin(vo.getLogin());
				u.setSenha(codificaSenha(vo.getSenha()));
				u.setOrganizations(new ArrayList<OrganizationElement>());
				
				for(OrganizationVO ovo: vo.getOrganizations()){
					OrganizationElement oe = (OrganizationElement) sessao.load(OrganizationElement.class, ovo.getId());
					u.getOrganizations().add(oe);
				}
				
				sessao.save(u);
				tx.commit();
				retorno = 0;
			}
			catch(Exception e){
				e.printStackTrace();
				tx.rollback();
				sessao.flush();
				
				retorno = 1;
			}
		}

		sessao.close();
		return retorno;
	}
	
	public boolean existeLogin(String login){
		Session sessao = HibernateUtil.getSession();
		Usuario u = new Usuario();
		u.setLogin(login);
		Criteria criterios = sessao.createCriteria(Usuario.class);
		criterios.add(Example.create(u));
		List<?> resultado = criterios.list();
		
		sessao.close();
		
		if (resultado.size() > 0){
			return true;
		}
		else{
			return false;
		}
	}

	public void updateUser(UsuarioVO vo) {
		Session sessao = HibernateUtil.getSession();
		Transaction tx = sessao.beginTransaction();
		
		try{
			Usuario u = getUser(vo.getId(), sessao);
			u.setNome(vo.getNome());
			u.setLogin(vo.getLogin());
			
			if (! vo.getSenha().equalsIgnoreCase(""))
				u.setSenha(codificaSenha(vo.getSenha()));
			
			u.setOrganizations(new ArrayList<OrganizationElement>());
			
			for(OrganizationVO ovo: vo.getOrganizations()){
				OrganizationElement oe = (OrganizationElement) sessao.load(OrganizationElement.class, ovo.getId());
				u.getOrganizations().add(oe);
			}
			
			sessao.update(u);
			tx.commit();
		}
		catch(Exception e){
			e.printStackTrace();
			tx.rollback();
			sessao.flush();
		}
		
		sessao.close();
	}
	
	public UsuarioVO getUser(String login){
		Session sessao = HibernateUtil.getSession();
		Usuario u = new Usuario();
		u.setLogin(login);
		Criteria criterios = sessao.createCriteria(Usuario.class);
		criterios.add(Example.create(u));
		List<?> resultado = criterios.list();
		
		UsuarioVO vo = new UsuarioVO();
		
		if (resultado.size() == 1){
			u = (Usuario) resultado.get(0);
			vo.setId(u.getId());
			vo.setLogin(u.getLogin());
			vo.setNome(u.getNome());
			vo.setSenha(u.getSenha());
		}
		
		sessao.close();
		return vo;		
	}
	
	public Usuario getUser(int id, Session sessao){
		Usuario u = (Usuario) sessao.load(Usuario.class, id);
		
		return u;
	}

	public Map<String, OrganizationVO> getOrganizations(int usuarioLogadoId) {
		Session sessao = HibernateUtil.getSession();
		Map<String, OrganizationVO> mapa = new HashMap<String, OrganizationVO>();
		
		if (usuarioLogadoId == -1){
			OrganizationDAO odao = new OrganizationDAO();
			for(OrganizationVO vo:odao.listOrganization()){
				mapa.put(Integer.toString(vo.getId()), vo);
			}
		}
		else{
			Usuario u = getUser(usuarioLogadoId, sessao);
			for(OrganizationElement oe:u.getOrganizations()){
				OrganizationVO vo = new OrganizationVO();
				vo.setId(oe.getId());
				vo.setNome(oe.getName());
				
				mapa.put(Integer.toString(oe.getId()), vo);
			}
			
		}
		
		sessao.close();
		return mapa;
	}	
}
